#include "Aabbs.hpp"

using namespace DirectX;

Aabb1::Aabb1(float minX, float minY, float minZ, float maxX, float maxY, float maxZ)
    : m_minPoint{minX, minY, minZ},
    m_maxPoint{maxX, maxY, maxZ}
{
}

std::int32_t btoi(bool b)
{
    return b == true ? 1 : 0;
}

GeometryState Aabb1::IntersectWithPlane(XMVECTOR plane) const
{
    const auto normal = DirectX::XMVectorAndInt(plane, g_XMMask3);
    XMFLOAT3 normalFloats;
    XMStoreFloat3(&normalFloats, normal);
    auto[x, y, z] = normalFloats;
    std::array<float, 3> nearPoint, farPoint;
    const auto select = [&](std::size_t index, bool neg) {
        if (neg) 
        {
            nearPoint[index] = m_maxPoint[index];
            farPoint[index] = m_minPoint[index];
        }
        else
        {
            nearPoint[index] = m_minPoint[index];
            farPoint[index] = m_maxPoint[index];
        }
    };

    select(0, x < 0.0f);
    select(1, y < 0.0f);
    select(2, z < 0.0f);
    XMFLOAT3 nearFloats{ nearPoint.data() }, farFloats{ farPoint.data() };
    XMVECTOR near{ XMLoadFloat3(&nearFloats) }, far{ XMLoadFloat3(&farFloats) };
    const auto result1 = XMVectorGetX(XMPlaneDotCoord(plane, near));
    const auto result2 = XMVectorGetX(XMPlaneDotCoord(plane, far));
    std::array<GeometryState, 3> states = {
        GeometryState::Inner,
        GeometryState::Intersect,
        GeometryState::Outer
    };
    std::size_t selector = btoi(result1 > 0.0f) + btoi(result2 > 0.0f);
    return states[selector];
}
